let express = require("express");
let app = express();

let birds = require("./birds");

/**
 * ==路由方法==
 * express 有很多路由方法
 * all 是一个特殊的路由方法，没有任何一个 HTTP 方法与之对应
 * 它的作用是对与一个路径上所有请求加载中间件
 * 
 * 如果希望 all 在某个路径上的任何请求 先 做一些业务逻辑，需要将 all 方法写在靠前的位置。
 * 否则将会略过 all
 * 
 * 这里，我们使用 all 处理 ‘/*’ 路径上的所有请求。
 */
app.all("/*", function(req, res, next){
    console.log("/* -> handler all");
    next();
});

/**
 * ==路由方法==
 * 最基本的路由方法，常用的路由方法还有 post 等
 */
app.get("/", function(req, res){
    console.log("/ -> handler \n");
    res.end("I am in GET '/' route.");
});

/**
 * ==路由 handler==
 * 路由 handler 可以使用多个回调函数
 * 注意，一定不要忘了 next 
 * 如果在下面的例子中，忘记了 next，则将无法 response
 */
app.get("/fuck", function(req, res, next){
    console.log("/fuck -> handler 01");

    res.send("fuck 01 <br/>");

    /**
     * 千万别忘了 next
     */
    next();
}, function(req, res){
    console.log("/fuck -> handler 02 \n")

    res.end("fuck 02");
});

/**
 * ==路由 handler==
 * 还可以使用回调函数数组
 */
let you01 = function(req, res, next){
    console.log("/you -> handler 01");
    next();
}

let you02 = function(req, res, next){
    console.log("/you -> handler 02");
    next();
}

let you03 = function(req, res){
    console.log("/you -> handler 03\n");
    res.end("you!");
}

app.get("/you", [you01, you02, you03]);

/**
 * ==路由 handler==
 * 还可以混合使用 回调函数数组 与 回调函数
 */
let off01 = function(req, res, next){
    console.log("/off -> handler 01");
    next();
}

let off02 = function(req, res, next){
    console.log("/off -> handler 02");
    next();
}

let off05 = function(req, res){
    console.log("/off -> handler 05");

    /**
     * res.download 响应下载文件
     * 
     * 注意：之后不能再调用其它res的方法
     */
    res.download("./files/fuckyou.json", function(err){
        if(err){
            console.log("/off download failed.");
            console.log(err.stack);
        }else{
            console.log("/off donwload successed.");
        }
    });
}

app.get("/off", [off01, off02], function(req, res, next){
    console.log("/off -> handler 03");
    next();
}, function(req, res, next){
    console.log("/off -> handler 04");
    next();
}, off05);

/**
 * ==路由 handler==
 * 使用 next('route') 将控制权交给下一个路由
 */

app.get("/me", function(req, res, next){
    console.log("/me -> handler 01");

    let flag = 1;
    if(flag === 1) next('route');
    else next();
}, function(req, res){
    console.log("/me -> handler 02");

    res.send("fuck me.");
});

app.get('/me', function(req, res){
    console.log("/me -> handler 03");

    res.send("fuck me too.");
});

/**
 * ==express.Router==
 */
app.use("/birds", birds);

/**
 * 处理错误
 */
app.get("/error", function(req, res){
    throw new Error("fuck");
});

app.use(function(err, req, res, next){
    console.log(err.stack);
    res.status(500).send("Something broke.");
});

/**
 * 处理 404
 * 原理在于，Express 执行了所有的中间件，但没有获取到任何输出
 * 在所有中间件最后添加这样一个中间件，可以适当处理 404.
 * 
 * 注意：必须是所有中间件最后。如果放置最前边，则 Express 会先执行这个中间件
 */
app.use(function(req, res, next){
    res.status(400).send("Sorry can't find that.");
});

app.listen(3000, function(){
    console.log("Listening on http://*:3000");
});